#include "Acceptor.h"
#include "Logger.h"
#include "InetAddress.h"
#include "EventLoop.h"

#include <sys/types.h>
#include <sys/socket.h>
#include <errno.h>
#include <unistd.h>

/**
 * @brief 创建非阻塞套接字文件
 *
 * @return int
 */
static int createNonblocking()
{
    int sockfd = ::socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0);
    if (sockfd < 0)
    {
        LOG_FATAL("%s:%s:%d listen socket create fail:%d", __FILE__, __FUNCTION__, __LINE__, errno);
    }
}
/**
 * @brief Construct a new Acceptor:: Acceptor object
 *
 * @param loop
 * @param listenAddr
 * @param reuseport
 */
Acceptor::Acceptor(EventLoop *loop, const InetAddress &listenAddr, bool reuseport)
    : loop_(loop), acceptSocket_(createNonblocking()), acceptChannel_(loop, acceptSocket_.fd()), listening_(false)
{
    // fd设置即绑定
    acceptSocket_.setReuseAddr(true);
    acceptSocket_.setReusePort(true);
    acceptSocket_.bindAddress(listenAddr);

    acceptChannel_.setReadCallback(std::bind(&Acceptor::handleRead, this));
}
/**
 * @brief 移除acceptChannel以及IO复用关注的event
 *
 */
Acceptor::~Acceptor()
{
    acceptChannel_.disableAll();
    acceptChannel_.remove();
}
/**
 * @brief 开启监听，关注fd的读事件
 *
 */
void Acceptor::listen()
{
    listening_ = true;
    acceptSocket_.lesten();
    acceptChannel_.enableReading();
}
/**
 * @brief 处理新用户链接
 *
 */
void Acceptor::handleRead()
{
    InetAddress peerAddr;
    int connfd = acceptSocket_.accept(&peerAddr);
    if (connfd >= 0)
    {
        if (newConnectionCallBack_) // 回调-封装成Channel->轮询分配给subLoop进行事件关注
        {
            newConnectionCallBack_(connfd, peerAddr);
        }
        else
        {
            ::close(connfd);
        }
    }
    else // 错误处理
    {
        LOG_ERROR("%s:%s:%d accept error:%d", __FILE__, __FUNCTION__, __LINE__, errno);
        if (errno == EMFILE)
        {
            LOG_ERROR("%s:%s:%d sockfd reached limit!", __FILE__, __FUNCTION__, __LINE__);
        }
    }
}